<?php 

namespace pmvc;

/**
 * An object for properties.
 *
 */
class Properties {

	private $parent 	= NULL;
	private $properties = Array();

	/**
	 * Creates a new Properties object setting it's
	 * parent to the one given.
	 * @param Properties $parent
	 */
	public function __construct(Properties $parent=NULL) {
		$this->parent = $parent;
	}

	/**
	 * Returns this Properties object's parent or
	 * NULL if there isn't a parent.
	 */
	public function getParent() {
		return $this->parent;
	}

	/**
	 * Sets the parent Properties object for this
	 * Properties object.
	 * @param Properties $parent
	 */
	public function setParent(Properties $parent) {
		$this->parent = $parent;
	}

	/**
	 * Returns the value of the given property.
	 * @param string $name
	 * @param mixed $default
	 */
	public function getProperty($name, $default=NULL) {
		if (array_key_exists($name, $this->properties)) {
			return $this->evalPropertyString($this->properties[$name]);
		} else if ($this->parent!=NULL) {
			return $this->parent->getProperty($name, $default);
		} else {
			return $default;
		}
	}

	/**
	 * Sets the value of the given property.
	 * @param string $name
	 * @param string $value
	 */
	public function setProperty($name, $value) {
		if (is_array($value)) {
			\pmvc\log\Log::warn("Refusing to set array property: {0}", $name);
		} else {
			$this->properties[$name] = $value;
		}
	}

	/**
	 * Evaluates the given property
	 */
	public function evalPropertyString($str) {
		if (!pmvc_hasVal($str)) { return NULL; }
		$props = $this;
		$str = preg_replace_callback('/\$\{(.*?)\}/', function($matches)use($props) {
			return $props->getProperty($matches[1]);
		}, $str);
		return $str;
	}

	/**
	 * Loads properties from the given file.
	 * @param string $file
	 */
	public function loadFromFile($file) {
		if (!file_exists($file)) {
			throw new Exception("Unable to load properties file: ".$file);
		}
		$xml = simplexml_load_file($file);
		if ($xml===FALSE) {
			throw new Exception("Unable to parse properties file: ".$file);
		}
		foreach ($xml->xpath("/pmvc-properties/property") as $prop) {
			$val = '';
			if (pmvc_hasVal($prop->attributes()->value)) {
				$val = (string)$prop->attributes()->value;
			} else if (pmvc_hasVal($prop->value)) {
				$val = (string)$prop->value;
			}
			$this->setProperty((string)$prop["name"], $val);
		}
	}
}


?>